﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace CardPlay.Client.Model
{
    public static class TreeNodeExtensions
    {
        public static int ToChildIndex(this ITreeNode node)
        {
            return node.ParentNode == null ? -1 : node.ParentNode.ChildNodes.TakeWhile(x => x != node).Count();
        }

        public static IEnumerable<ITreeNode> Siblings(this ITreeNode node)
        {
            return node.ParentNode == null ? Enumerable.Empty<ITreeNode>() : node.ParentNode.ChildNodes.Where(n => n != node);
        }

        public static IEnumerable<ITreeNode> SelfWithAncestors(this ITreeNode node)
        {
            return Enumerable.Repeat(node, 1).Concat(node.Ancestors());
        }

        public static IEnumerable<ITreeNode> SelfWithDescendants(this ITreeNode root)
        {
            return Enumerable.Repeat(root, 1).Concat(root.Descendants());
        }

        public static IEnumerable<ITreeNode> Ancestors(this ITreeNode node)
        {
            for (var ancestor = node.ParentNode; ancestor != null; ancestor = ancestor.ParentNode)
                yield return ancestor;
        }

        public static IEnumerable<ITreeNode> Descendants(this ITreeNode root)
        {
            foreach (var node in root.ChildNodes)
            {
                yield return node;

                foreach (var descendant in node.Descendants())
                    yield return descendant;
            }
        }

        public static object GetService(this ITreeNode node, Type type)
        {
            return node
                .SelfWithAncestors()
                .OfType<IServiceProvider>()
                .Select(provider => provider.GetService(type))
                .FirstOrDefault(result => result != null);
        }

        public static T GetService<T>(this ITreeNode node) where T : class
        {
            return (T) node.GetService(typeof(T));
        }
    }
}